
import WTool from "./WTool";

const { ccclass, property } = cc._decorator;

export enum Touch_ObjectType {
    单击按下触发 = 0,
    拖拽到某位置放开触发 = 1,//TargetNodes[0]就是位置对象
    方向拖拽抬起触发 = 2,
    拖拽放开多点触发 = 3,//TargetNodes就是位置对象
}
export enum Touch_CalculateType {
    范围测算 = 0,
    Box盒子测算 = 1,
    物理Collider测算 = 2, //使用Collider测算必须在身上挂上一个碰撞盒子
}
@ccclass
export default class TouchMonitor extends cc.Component {
    @property
    ID: number = 0;
    @property({ type: cc.Enum(Touch_ObjectType) })
    ObjectType: Touch_ObjectType = Touch_ObjectType.单击按下触发;
    @property({ type: cc.Enum(Touch_CalculateType) })
    Touch_CalculateType: Touch_CalculateType = Touch_CalculateType.范围测算;
    @property({ type: [cc.Node] })
    TargetNodes: Array<cc.Node> = [];//目标对象
    public InitPoint: cc.Vec3 = null;
    public upliftDistance: number = 80;//距离测算下的距离半径
    public Offset: cc.Vec2 = cc.v2(0, 0);// 触发偏移
    //---------拖动处于最上层-------------------------//使用此功能需要在移动和抬起的地方判断initpoint是否存在
    public Onstratosphere: boolean = false;//物体拖动时是否处于最上层
    private Father: cc.Node = null;//父物体
    private SiblingIndex: number = 0;//同级索引
    private temporaryScale: number = 1;//临时缩放
    //----------------------------------------------
    //拖动的时候会自动旋转
    public IsAngel: boolean = false;
    public AngelNumber: number = 30;
    //-----------------------------------------


    //---------------------------------------------可继承方法--------------------------------------------------
    //事件接口,拖拽到某位置放开触发_触发事件
    TouchMoveInCident(TargetNode: cc.Node) {

    }
    //事件接口，拖拽到某位置放开未触发，与TouchMoveInCident这个方法对立
    TouchHoming(TargetNode: cc.Node) {

    }
    //事件接口,可拖拽的物体在拖拽过程中(每帧调用)
    TouchMoveCourse(even) {

    }
    public DragDistance: number = 30;// 方向滑动触发的最小距离(滑动小于距离px则不会执行以下四个方法)
    //事件接口（物体向下滑动）：类型:2.方向拖拽抬起触发
    Drag_Down() {

    }
    //事件接口（物体向上滑动）：类型:2.方向拖拽抬起触发
    Drag_Up() {

    }
    //事件接口（物体向左滑动）：类型:2.方向拖拽抬起触发
    Drag_Left() {

    }
    //事件接口（物体向右滑动）：类型:2.方向拖拽抬起触发
    Drag_Right() {

    }
    //条件判断（在）
    ConditionalJudgment(): boolean { //部分情况可以拖动物体但是条件没有达到不会发生效果，可以重写这个方法，条件成立返回true，不成立返回false
        return true;
    }

    //---------------------------------------------可继承方法--------------------------------------------------



    start() {
        switch (this.ObjectType) {
            case 0: this.node.on(cc.Node.EventType.TOUCH_START, (even) => { this.OnTouchDown(even); });
                this.node.on(cc.Node.EventType.TOUCH_END, (even) => { this.OnTouchUp(even); }); break;
            case 1: this.node.on(cc.Node.EventType.TOUCH_START, (even) => { this.OnTouchDown(even); });
                this.node.on(cc.Node.EventType.TOUCH_MOVE, (even) => { this.OnTouchMove(even); });
                this.node.on(cc.Node.EventType.TOUCH_END, (even) => { this.OnTouchUp(even); });
                this.node.on(cc.Node.EventType.TOUCH_CANCEL, (even) => { this.OnTouchUp(even); }); break;
            case 2: this.node.on(cc.Node.EventType.TOUCH_START, (even) => { this.OnTouchDown(even); });
                this.node.on(cc.Node.EventType.TOUCH_END, (even) => { this.OnDirectionTouchUp(even); });
                this.node.on(cc.Node.EventType.TOUCH_CANCEL, (even) => { this.OnDirectionTouchUp(even); }); break;
            case 3: this.node.on(cc.Node.EventType.TOUCH_START, (even) => { this.OnTouchDown(even); });
                this.node.on(cc.Node.EventType.TOUCH_MOVE, (even) => { this.OnTouchMove(even); });
                this.node.on(cc.Node.EventType.TOUCH_END, (even) => { this.OnTouchUp(even); });
                this.node.on(cc.Node.EventType.TOUCH_CANCEL, (even) => { this.OnTouchUp(even); }); break;
        }
        if (this.Touch_CalculateType == Touch_CalculateType.物理Collider测算) {
            cc.director.getCollisionManager().enabled = true;
        }
    }

    public _Colliders: cc.Collider[] = [];
    onCollisionEnter(other: cc.Collider, self) {
        this._Colliders.push(other);
    }
    onCollisionExit(other: cc.Collider, self) {
        let index = this._Colliders.indexOf(other);
        if (index >= 0) {
            this._Colliders.splice(index, 1);
        }
    }
    //触摸按下
    OnTouchDown(even) {
        this.InitPoint = this.node.position;
        if (this.Onstratosphere) {//拖动处于最上层
            this.InitPoint = this.node.position;
            this.temporaryScale = this.node.scale;
            let WorldScale = WTool.getWorldScale(this.node);
            this.Father = this.node.parent;
            this.SiblingIndex = this.node.getSiblingIndex();
            WTool.SetParent(this.node, cc.find("Canvas"));
            this.node.scale = WorldScale;
        }
        if (this.IsAngel) {
            this.node.angle = this.node.angle + this.AngelNumber;
        }
        if (this.ObjectType == 2) {//方向拖拽
            if (this.InitPoint == null) {
                this.InitPoint = even.getLocation();
            }
        }
    }
    //触摸拖拽
    OnTouchMove(even) {
        if (this.InitPoint == null) {
            this.InitPoint = this.node.position;
        }
        let x = even.getLocationX();
        let y = even.getLocationY();
        if (this.ObjectType == Touch_ObjectType.拖拽到某位置放开触发) {
            WTool.setWorldPos(this.node, cc.v2(x, y));
        }
        if (this.ObjectType == Touch_ObjectType.拖拽放开多点触发) {
            WTool.setWorldPos(this.node, cc.v2(x, y));
        }
        this.TouchMoveCourse(even);
    }

    //触摸抬起
    OnTouchUp(even) {
        if (this.Onstratosphere) {
            this.node.scale = this.temporaryScale;
            this.node.setParent(this.Father);
            this.node.setSiblingIndex(this.SiblingIndex);
        }
        if (this.IsAngel) {
            this.node.angle = this.node.angle - this.AngelNumber;
        }
        if (!this.ConditionalJudgment()) { //游戏条件未达成直接返回初始位置
            this.node.position = this.InitPoint;
            return;
        };
        let TriggeringCondition: boolean = false;//触发条件是否达成
        if (this.ObjectType == Touch_ObjectType.拖拽到某位置放开触发) {
            if (this.Touch_CalculateType == Touch_CalculateType.范围测算) {
                let Distance = (even.getLocation().add(this.Offset)).sub(WTool.getWorldPos(this.TargetNodes[0])).mag();
                if (Distance > this.upliftDistance) TriggeringCondition = true;
            }
            if (this.Touch_CalculateType == Touch_CalculateType.Box盒子测算) {
                if (this.TargetNodes[0].getBoundingBoxToWorld().contains(even.getLocation())) TriggeringCondition = true;
            }
            if (this.Touch_CalculateType == Touch_CalculateType.物理Collider测算) {
                if (this._Colliders.indexOf(this.TargetNodes[0].getComponent(cc.Collider)) != -1) TriggeringCondition = true;
            }
            if (TriggeringCondition) {
                this.TouchMoveInCident(this.TargetNodes[0]);
            } else {
                if (this.InitPoint) this.node.position = this.InitPoint;
                this.TouchHoming(this.TargetNodes[0]);
            }
        }
        let index: number = 0;//触发的下标
        if (this.ObjectType == Touch_ObjectType.拖拽放开多点触发) {
            if (this.Touch_CalculateType == Touch_CalculateType.范围测算) {
                for (let i = 0; i < this.TargetNodes.length; i++) {
                    if (this.TargetNodes[i].name == "") {
                        continue;
                    }
                    let Distance = (even.getLocation().add(this.Offset)).sub(WTool.getWorldPos(this.TargetNodes[i])).mag();
                    if (Distance > this.upliftDistance) {
                        TriggeringCondition = true;
                        index = i;
                        break;
                    }
                }
            }
            if (this.Touch_CalculateType == Touch_CalculateType.Box盒子测算) {
                for (let i = 0; i < this.TargetNodes.length; i++) {
                    if (this.TargetNodes[i].name == "") {
                        continue;
                    }
                    if (this.TargetNodes[i].getBoundingBoxToWorld().contains(even.getLocation())) {
                        TriggeringCondition = true;
                        index = i;
                        break;
                    }
                }
            }
            if (this.Touch_CalculateType == Touch_CalculateType.物理Collider测算) {
                for (let i = 0; i < this.TargetNodes.length; i++) {
                    if (this.TargetNodes[i].name == "") {
                        continue;
                    }
                    if (this._Colliders.indexOf(this.TargetNodes[i].getComponent(cc.Collider)) != -1) {
                        TriggeringCondition = true;
                        index = i;
                        break;
                    }

                }
            }
            if (TriggeringCondition) {
                this.TouchMoveInCident(this.TargetNodes[index]);
            } else {
                if (this.InitPoint) this.node.position = this.InitPoint;
                this.TouchHoming(this.TargetNodes[index]);
            }
        }
    }

    //方向拖拽抬起
    OnDirectionTouchUp(even) {
        let Point: cc.Vec2 = even.getLocation();
        if (!this.InitPoint) return;
        if (Point.x > this.InitPoint.x + this.DragDistance) {//向右拖拽
            this.Drag_Right();
        }
        if (Point.x < this.InitPoint.x - this.DragDistance) {//向左拖拽
            this.Drag_Left();
        }
        if (Point.y > this.InitPoint.y + this.DragDistance) {//向上拖拽
            this.Drag_Up();
        }
        if (Point.y < this.InitPoint.y - this.DragDistance) {//向下拖拽
            this.Drag_Down();
        }
    }

    //归位（拖拽物体不通过抬起鼠标强制归位到初始位置）
    Restoration() {
        if (this.Onstratosphere) {
            this.node.scale = this.temporaryScale;
            this.node.setParent(this.Father);
            this.node.setSiblingIndex(this.SiblingIndex);
        }
        this.node.position = this.InitPoint;
    }
    //注销自身所有事件
    writeoff() {
        this.node.off(cc.Node.EventType.TOUCH_START);
        this.node.off(cc.Node.EventType.TOUCH_MOVE);
        this.node.off(cc.Node.EventType.TOUCH_CANCEL);
        this.node.off(cc.Node.EventType.TOUCH_END);
    }
}
